package com.dims_hsrc.audit.service.impl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
import com.aspose.words.FindReplaceOptions;
import com.aspose.words.FindReplaceDirection;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.dims_hsrc.common.core.text.Convert;
import com.dims_hsrc.common.exception.ServiceException;
import com.dims_hsrc.common.utils.DateUtils;
import com.dims_hsrc.common.utils.StringUtils;
import com.dims_hsrc.common.utils.uuid.IdUtils;
import com.dims_hsrc.audit.domain.ContractRecord;
import com.dims_hsrc.audit.mapper.ContractRecordMapper;
import com.dims_hsrc.audit.service.IContractRecordService;


/**
 * 合同记录Service业务层处理
 * 
 * @author 赵浩然
 */
@Service
public class ContractRecordServiceImpl implements IContractRecordService 
{
    private static final Logger log = LoggerFactory.getLogger(ContractRecordServiceImpl.class);
    
    @Autowired
    private ContractRecordMapper contractRecordMapper;
    
    @Value("${contract.template.path}")
    private String templatePath;
    
    @Value("${contract.template.default-template}")
    private String defaultTemplate;
    
    @Value("${contract.output.path}")
    private String outputPath;
    
    @Value("${contract.output.default-format}")
    private String defaultFormat;
    
    @Value("${contract.numbering.prefix}")
    private String contractPrefix;
    
    @Value("${contract.numbering.date-format}")
    private String contractDateFormat;
    
    @Value("${contract.numbering.sequence-length}")
    private int sequenceLength;
    
    @Value("${contract.numbering.separator}")
    private String separator;
    
    @Value("${dims-hsrc.contract}")
    private String contractPath;
    
    @Value("${aspose.license.path:}")
    private String licensePath;
    
    @Value("${aspose.license.enabled:false}")
    private boolean licenseEnabled;



    /**
     * 查询合同记录
     * 
     * @param id 合同记录ID
     * @return 合同记录
     */
    @Override
    public ContractRecord selectContractRecordById(String id)
    {
        return contractRecordMapper.selectContractRecordById(id);
    }

    /**
     * 查询合同记录列表
     * 
     * @param contractRecord 合同记录
     * @return 合同记录
     */
    @Override
    public List<ContractRecord> selectContractRecordList(ContractRecord contractRecord)
    {
        return contractRecordMapper.selectContractRecordList(contractRecord);
    }

    /**
     * 根据结构ID查询合同记录
     * 
     * @param structId 结构ID
     * @return 合同记录集合
     */
    @Override
    public List<ContractRecord> selectContractRecordsByStructId(String structId)
    {
        return contractRecordMapper.selectContractRecordsByStructId(structId);
    }

    /**
     * 根据合同编号查询合同记录
     * 
     * @param contractNo 合同编号
     * @return 合同记录
     */
    @Override
    public ContractRecord selectContractRecordByContractNo(String contractNo)
    {
        return contractRecordMapper.selectContractRecordByContractNo(contractNo);
    }

    /**
     * 新增合同记录
     * 
     * @param contractRecord 合同记录
     * @return 结果
     */
    @Override
    public int insertContractRecord(ContractRecord contractRecord)
    {
        // 如果ID为空，则生成UUID
        if (StringUtils.isEmpty(contractRecord.getId())) {
            contractRecord.setId(IdUtils.guid());
        }
        contractRecord.setCreateTime(DateUtils.getNowDate());
        return contractRecordMapper.insertContractRecord(contractRecord);
    }

    /**
     * 修改合同记录
     * 
     * @param contractRecord 合同记录
     * @return 结果
     */
    @Override
    public int updateContractRecord(ContractRecord contractRecord)
    {
        return contractRecordMapper.updateContractRecord(contractRecord);
    }

    /**
     * 删除合同记录对象
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteContractRecordByIds(String ids)
    {
        return contractRecordMapper.deleteContractRecordByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除合同记录信息
     * 
     * @param id 合同记录ID
     * @return 结果
     */
    @Override
    public int deleteContractRecordById(String id)
    {
        return contractRecordMapper.deleteContractRecordById(id);
    }
    
    /**
     * 更新合同状态
     * 
     * @param contractRecord 合同记录
     * @return 结果
     */
    @Override
    public int updateContractStatus(ContractRecord contractRecord)
    {
        return contractRecordMapper.updateContractStatus(contractRecord);
    }
    
    /**
     * 生成合同
     * 
     * @param contractRecord 合同信息
     * @return 合同记录
     */
    @Override
    public ContractRecord generateContract(ContractRecord contractRecord)
    {
        try {
            log.info("开始生成合同");

            // 确保目录存在
            ensureDirectoriesExist();

            // 设置UUID
            if (StringUtils.isEmpty(contractRecord.getId())) {
                contractRecord.setId(IdUtils.guid());
            }

            // 1. 生成合同编号
            if (StringUtils.isEmpty(contractRecord.getContractNo())) {
                contractRecord.setContractNo(generateContractNo());
            }

            // 2. 设置生成状态
            contractRecord.setStatus("GENERATED");

            // 3. 加载模板
            File templateDir = new File(templatePath);
            if (!templateDir.exists()) {
                // 尝试使用相对路径
                templateDir = new File(System.getProperty("user.dir"), templatePath);
            }

            // 使用前端传来的模板路径，如果没有则使用默认模板
            String templateFileName = StringUtils.isNotEmpty(contractRecord.getTemplatePath()) 
                ? contractRecord.getTemplatePath() 
                : defaultTemplate;
            
            // 如果模板路径包含完整路径，直接使用
            File templateFileObj;
            if (templateFileName.startsWith("contract/templates/")) {
                // 移除前缀，只保留文件名
                templateFileName = templateFileName.substring("contract/templates/".length());
            }
            
            String templateFile = templateDir.getAbsolutePath() + File.separator + templateFileName;
            log.info("使用模板: {}", templateFile);

            templateFileObj = new File(templateFile);
            if (!templateFileObj.exists()) {
                log.error("模板文件不存在: {}", templateFile);
                throw new ServiceException("模板文件不存在: " + templateFile);
            }

            // 4. 确定输出文件路径
            String fileName = contractRecord.getContractNo() + "." + defaultFormat;

            File outputDir = new File(outputPath);
            if (!outputDir.exists()) {
                // 尝试使用相对路径
                outputDir = new File(System.getProperty("user.dir"), outputPath);
            }

            String outputFile = outputDir.getAbsolutePath() + File.separator + fileName;

            // 设置文件路径 - 确保使用绝对路径
            contractRecord.setFilePath(outputFile);

            // 加载模板文件
            Document doc = new Document(templateFile);

            // 创建 FindReplaceOptions
            FindReplaceOptions options = new FindReplaceOptions();
            options.setDirection(FindReplaceDirection.FORWARD);
            options.setFindWholeWordsOnly(false);

            // 替换合同基本信息
            doc.getRange().replace("${contractNo}", contractRecord.getContractNo(), options);
            doc.getRange().replace("${contractTitle}", contractRecord.getContractTitle(), options);
            doc.getRange().replace("${structName}", contractRecord.getStructName(), options);
            doc.getRange().replace("${structId}", contractRecord.getStructId(), options);
            doc.getRange().replace("${partyA}", contractRecord.getPartyA(), options);
            doc.getRange().replace("${partyB}", contractRecord.getPartyB(), options);

            // 替换签订日期为当前日期
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
            String formattedDate = sdf.format(new Date());
            doc.getRange().replace("${signDate}", formattedDate, options);

            // 处理技术指标JSON数据
            if (StringUtils.isNotEmpty(contractRecord.getIndicatorsJson())) {
                StringBuilder indicatorsTable = new StringBuilder();
                ObjectMapper mapper = new ObjectMapper();
                try {
                    List<Object> indicators = mapper.readValue(contractRecord.getIndicatorsJson(), List.class);

                    for (int i = 0; i < indicators.size(); i++) {
                        Object indicator = indicators.get(i);
                        if (indicator instanceof java.util.Map) {
                            java.util.Map<String, Object> item = (java.util.Map<String, Object>) indicator;
                            String type = (String) item.getOrDefault("type", "");
                            String name = (String) item.getOrDefault("name", "");
                            String value = (String) item.getOrDefault("value", "");
                            String unit = (String) item.getOrDefault("unit", "");
                            String standard = (String) item.getOrDefault("standard", "");

                            // 根据类型进行不同的格式化
                            if ("knowledge_mapping".equalsIgnoreCase(type) || "direct_mapping".equalsIgnoreCase(type)) {
                                // 知识映射和直接映射只输出值
                                indicatorsTable.append(value);
                            } else {
                                // 其他类型的指标使用表格式布局
                                indicatorsTable.append(name).append("：");
                                indicatorsTable.append(value);
                                if (StringUtils.isNotEmpty(unit)) {
                                    indicatorsTable.append(" ").append(unit);
                                }
                                if (StringUtils.isNotEmpty(standard)) {
                                    // 使用实际的换行符
                                    indicatorsTable.append(System.lineSeparator()).append("标准：").append(standard);
                                }
                            }

                            // 在每个技术指标后添加两个换行符，确保段落分隔
                            indicatorsTable.append(System.lineSeparator()).append(System.lineSeparator());
                        }
                    }
                } catch (Exception e) {
                    log.warn("处理技术指标数据异常", e);
                    indicatorsTable.append("技术指标数据格式错误");
                }

                doc.getRange().replace("${indicatorsJson}", indicatorsTable.toString(), options);
            } else {
                doc.getRange().replace("${indicatorsJson}", "暂无技术指标", options);
            }

            // 根据文件格式保存文档
            if ("pdf".equalsIgnoreCase(defaultFormat)) {
                doc.save(outputFile, SaveFormat.PDF);
            } else {
                doc.save(outputFile, SaveFormat.DOCX);
            }

            log.info("文档已生成: {}", outputFile);

            // 保存合同记录到数据库
            insertContractRecord(contractRecord);

            return contractRecord;
        } catch (Exception e) {
            log.error("生成合同失败", e);
            throw new ServiceException("生成合同失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取合同文件路径
     * 
     * @param contractNo 合同编号
     * @return 文件路径
     */
    @Override
    public String getContractFilePath(String contractNo) {
        ContractRecord record = contractRecordMapper.selectContractRecordByContractNo(contractNo);
        if (record != null && StringUtils.isNotEmpty(record.getFilePath())) {
            return record.getFilePath();
        }
        throw new ServiceException("未找到合同文件");
    }
    
    /**
     * 生成新的合同编号
     * 
     * @return 合同编号
     */
    @Override
    public String generateContractNo() {
        // 获取当前日期
        String dateStr = new SimpleDateFormat(contractDateFormat).format(new Date());
        
        // 查询当天最新的合同编号
        String prefix = contractPrefix + separator + dateStr;
        String latestNo = contractRecordMapper.selectLatestContractNoByPrefix(prefix);
        
        int sequence = 1;
        if (latestNo != null) {
            // 解析序号
            String[] parts = latestNo.split(separator);
            if (parts.length > 2) {
                try {
                    sequence = Integer.parseInt(parts[2]) + 1;
                } catch (NumberFormatException e) {
                    // 如果解析失败，使用默认值1
                }
            }
        }
        
        // 格式化序号
        String sequenceStr = String.format("%0" + sequenceLength + "d", sequence);
        
        // 组装合同编号
        return contractPrefix + separator + dateStr + separator + sequenceStr;
    }
    
    /**
     * 从资源复制默认模板
     */
    private void copyDefaultTemplate(File templateDir) throws IOException {
        log.info("尝试复制默认模板到目录: {}", templateDir.getAbsolutePath());
        
        // 创建一个空白的基本模板，而不是尝试从资源加载
        File defaultTemplateFile = new File(templateDir, defaultTemplate);
        try {
            // 从资源中加载
            InputStream is = getClass().getResourceAsStream("/templates/default_contract_template.docx");
            
            if (is != null) {
                // 如果资源存在，使用资源
                try (FileOutputStream fos = new FileOutputStream(defaultTemplateFile)) {
                    byte[] buffer = new byte[1024];
                    int length;
                    while ((length = is.read(buffer)) > 0) {
                        fos.write(buffer, 0, length);
                    }
                }
                is.close();
                log.info("已从资源复制默认模板");
            } else {
                // 如果找不到默认模板，记录错误并抛出异常
                log.error("找不到默认模板资源文件，请确保resources/templates下存在default_contract_template.docx文件");
                throw new ServiceException("找不到默认模板资源，请联系管理员添加模板文件");
            }
        } catch (Exception e) {
            log.error("复制默认模板失败", e);
            throw new ServiceException("复制默认模板失败: " + e.getMessage());
        }
    }

    /**
     * 确保必要的目录结构存在
     */
    private void ensureDirectoriesExist() {
        try {
            log.info("检查并创建必要的目录结构");
            
            // 确保模板目录存在
            File templateDir = new File(templatePath);
            if (!templateDir.exists()) {
                log.info("模板目录不存在，尝试创建: {}", templateDir.getAbsolutePath());
                if (!templateDir.mkdirs()) {
                    log.warn("无法创建模板目录，尝试使用相对路径");
                    // 尝试使用相对路径
                    templateDir = new File(System.getProperty("user.dir"), templatePath);
                    if (!templateDir.exists() && !templateDir.mkdirs()) {
                        throw new ServiceException("无法创建模板目录: " + templateDir.getAbsolutePath());
                    }
                }
                log.info("已创建模板目录: {}", templateDir.getAbsolutePath());
                
                // 如果模板目录是新创建的，复制默认模板
                copyDefaultTemplate(templateDir);
            }
            
            // 检查默认模板是否存在
            File defaultTemplateFile = new File(templateDir, defaultTemplate);
            if (!defaultTemplateFile.exists()) {
                log.info("默认模板不存在，尝试复制: {}", defaultTemplateFile.getAbsolutePath());
                // 如果默认模板不存在，复制默认模板
                copyDefaultTemplate(templateDir);
            }
            
            // 确保输出目录存在
            File outputDir = new File(outputPath);
            if (!outputDir.exists()) {
                log.info("输出目录不存在，尝试创建: {}", outputDir.getAbsolutePath());
                if (!outputDir.mkdirs()) {
                    log.warn("无法创建输出目录，尝试使用相对路径");
                    // 尝试使用相对路径
                    outputDir = new File(System.getProperty("user.dir"), outputPath);
                    if (!outputDir.exists() && !outputDir.mkdirs()) {
                        throw new ServiceException("无法创建输出目录: " + outputDir.getAbsolutePath());
                    }
                }
                log.info("已创建输出目录: {}", outputDir.getAbsolutePath());
            }
        } catch (Exception e) {
            log.error("创建目录结构失败", e);
            throw new ServiceException("创建目录结构失败: " + e.getMessage());
        }
    }

    /**
     * 替换合同文件
     * 
     * @param contractNo 合同编号
     * @param file 新的合同文件
     * @return 结果
     */
    @Override
    public int replaceContractFile(String contractNo, MultipartFile file) {
        try {
            // 1. 获取原合同记录
            ContractRecord record = contractRecordMapper.selectContractRecordByContractNo(contractNo);
            if (record == null) {
                throw new ServiceException("未找到合同记录");
            }

            // 2. 确保输出目录存在
            File outputDir = new File(outputPath);
            if (!outputDir.exists()) {
                // 尝试使用相对路径
                outputDir = new File(System.getProperty("user.dir"), outputPath);
                if (!outputDir.exists()) {
                    // 创建目录
                    if (!outputDir.mkdirs()) {
                        throw new ServiceException("无法创建输出目录: " + outputDir.getAbsolutePath());
                    }
                }
            }

            // 检查目录是否可写
            if (!outputDir.canWrite()) {
                throw new ServiceException("输出目录没有写入权限: " + outputDir.getAbsolutePath());
            }

            // 3. 删除原文件
            String oldFilePath = record.getFilePath();
            if (StringUtils.isNotEmpty(oldFilePath)) {
                File oldFile = new File(oldFilePath);
                if (oldFile.exists()) {
                    if (!oldFile.delete()) {
                        log.warn("无法删除原合同文件: {}", oldFilePath);
                    }
                }
            }

            // 4. 保存新文件
            String fileName = contractNo + "." + defaultFormat;
            String newFilePath = outputDir.getAbsolutePath() + File.separator + fileName;
            File newFile = new File(newFilePath);
            
            // 确保父目录存在
            File parentDir = newFile.getParentFile();
            if (parentDir != null && !parentDir.exists()) {
                if (!parentDir.mkdirs()) {
                    throw new ServiceException("无法创建文件父目录: " + parentDir.getAbsolutePath());
                }
            }

            // 使用 try-with-resources 确保流正确关闭
            try (InputStream inputStream = file.getInputStream();
                 FileOutputStream outputStream = new FileOutputStream(newFile)) {
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
                outputStream.flush();
            }

            // 5. 更新合同记录
            record.setFilePath(newFilePath);
            record.setUpdateTime(DateUtils.getNowDate());
            
            // 6. 如果合同已上链，更新链上状态
            if ("CONFIRMED".equals(record.getChainStatus())) {
                record.setChainStatus("PENDING");
                record.setTxHash(null);
                record.setChainTime(null);
                record.setChainCertNo(null);
            }

            return contractRecordMapper.updateContractRecord(record);
        } catch (Exception e) {
            log.error("替换合同文件失败", e);
            throw new ServiceException("替换合同文件失败: " + e.getMessage());
        }
    }
}